package com.neusoft.neuiotms.dcam.workflow.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.EntityNotFoundException;
import javax.transaction.Transactional;

import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.apache.cxf.common.util.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.neusoft.bizcore.activiti.dto.ProcessInstanceDTO;
import com.neusoft.bizcore.activiti.service.ProcessInstanceService;
import com.neusoft.bizcore.activiti.service.WorkOrderService;
import com.neusoft.bizcore.auth.common.bean.UserBean;
import com.neusoft.bizcore.web.constant.ExceptionConstants;
import com.neusoft.bizcore.web.exception.UnitedException;
import com.neusoft.bizcore.web.support.Searchable;
import com.neusoft.neuiotms.common.constant.AHConstants;
import com.neusoft.neuiotms.dcam.anhui.itsm.ContractBean;
import com.neusoft.neuiotms.dcam.anhui.itsm.ContractBean.AssetBean;
import com.neusoft.neuiotms.dcam.anhui.itsm.WorkflowBean;
import com.neusoft.neuiotms.dcam.constant.DCAMConsts;
import com.neusoft.neuiotms.dcam.fixed.dto.AssetDTO;
import com.neusoft.neuiotms.dcam.fixed.dto.AssetLifeCycleDTO;
import com.neusoft.neuiotms.dcam.fixed.dto.GoodsFileDTO;
import com.neusoft.neuiotms.dcam.fixed.dto.WarehouseRecordDTO;
import com.neusoft.neuiotms.dcam.fixed.model.Asset;
import com.neusoft.neuiotms.dcam.fixed.model.AssetType;
import com.neusoft.neuiotms.dcam.fixed.repository.AssetRepository;
import com.neusoft.neuiotms.dcam.fixed.repository.AssetTypeRepository;
import com.neusoft.neuiotms.dcam.fixed.service.AssetLifeCycleService;
import com.neusoft.neuiotms.dcam.fixed.service.AssetService;
import com.neusoft.neuiotms.dcam.fixed.service.GoodsFileService;
import com.neusoft.neuiotms.dcam.fixed.service.ItsmService;
import com.neusoft.neuiotms.dcam.fixed.service.WarehouseRecordService;
import com.neusoft.neuiotms.dcam.workflow.converter.ITSMApproveConverter;
import com.neusoft.neuiotms.dcam.workflow.converter.RukuKJConverter;
import com.neusoft.neuiotms.dcam.workflow.dto.ITSMApproveDTO;
import com.neusoft.neuiotms.dcam.workflow.dto.RukuKJAssetDTO;
import com.neusoft.neuiotms.dcam.workflow.dto.RukuKJDTO;
import com.neusoft.neuiotms.dcam.workflow.dto.RukuKJGoodsFileDTO;
import com.neusoft.neuiotms.dcam.workflow.model.ITSMApprove;
import com.neusoft.neuiotms.dcam.workflow.model.RukuKJ;
import com.neusoft.neuiotms.dcam.workflow.model.RukuKJAsset;
import com.neusoft.neuiotms.dcam.workflow.model.WorkOrderDeposit;
import com.neusoft.neuiotms.dcam.workflow.repository.ITSMApproveRepository;
import com.neusoft.neuiotms.dcam.workflow.repository.RukuKJRepository;
import com.neusoft.neuiotms.dcam.workflow.repository.WorkOrderDepositRepository;
import com.neusoft.neuiotms.dcam.workflow.service.RukuKJService;
import com.neusoft.neuiotms.micro.auth.AuthMicroService;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class RukuKJServiceImpl implements RukuKJService {

    @Autowired
    private ProcessInstanceService processInstanceService;
    @Autowired
    private ITSMApproveRepository approveRepository;
    @Autowired
    private ITSMApproveConverter approveConverter;
    @Autowired
    private WorkOrderService workOrderService;
    @Autowired
    private RukuKJRepository rukuKJRepository;
    @Autowired
    private RukuKJConverter rukuKJConverter;
    @Autowired
    private AssetRepository assetRepository;
    @Autowired
    private AssetService assetService;
    @Autowired
    private WarehouseRecordService warehouseRecordService;
    @Autowired
    private AssetLifeCycleService assetLifeCycleService;
    @Autowired
    private GoodsFileService goodsFileService;
    @Autowired
    private AuthMicroService authMicroService;
    @Autowired
    private AssetTypeRepository assetTypeRepository;
    @Autowired
    private ItsmService itsmService;
    @Autowired
    private WorkOrderDepositRepository workOrderDepositRepository;

    @Override
    public RukuKJDTO itsmCreate(final ContractBean bean) {

        final RukuKJDTO dto = new RukuKJDTO();

        dto.setTitle(bean.getContractName() + "入库");
        dto.setReceiveDate(new Date());
        dto.setContractCode(bean.getContractId());
        dto.setContractName(bean.getContractName());
        dto.setCategories("1");
        dto.setAutogenerate(true);
        dto.setTemporary(true);

        // 资产信息
        final List<AssetBean> assets = bean.getAssetList();
        if ((null != assets) && (assets.size() > 0)) {
            for (final AssetBean asset : assets) {
                switch (asset.getAssetType()) {
                // 资产
                case "1":
                    for (int j = 0; j < asset.getAssetNumber(); j++) {
                        final RukuKJAssetDTO rukuAsset = new RukuKJAssetDTO();
                        rukuAsset.setPurchaseDate(new Date());
                        /** 设备名称 */
                        rukuAsset.setName(asset.getAssetName());
                        /** 设备分类ID */
                        final AssetType type = this.assetTypeRepository.findByCode(asset.getAssetClassID());
                        rukuAsset.setSmallTypeCode(type.getCode());
                        rukuAsset.setSmallTypeName(type.getName());
                        if (type.getParent() != null) {
                            rukuAsset.setMiddleTypeCode(type.getParent().getCode());
                            rukuAsset.setMiddleTypeName(type.getParent().getName());
                            if (null != type.getParent().getParent()) {
                                rukuAsset.setBigTypeCode(type.getParent().getParent().getCode());
                                rukuAsset.setBigTypeName(type.getParent().getParent().getName());
                            }
                        }

                        /** 设备品牌 */
                        rukuAsset.setBrand(asset.getAssetSign());
                        /** 设备型号 */
                        rukuAsset.setSpecifications(asset.getAssetModel());
                        /** 设备单位 */
                        rukuAsset.setMeasureUnit(asset.getAssetUnit());
                        /** 设备单价 */
                        rukuAsset.setMoney(asset.getAssetPrice());
                        /** 设备数量 */
                        rukuAsset.setAmount(1);
                        rukuAsset.setBelongs(AHConstants.BELONG_KJ_CODE);
                        // 2022-04-08 ge.x 增加合同
                        rukuAsset.setContractName(bean.getContractName());
                        rukuAsset.setContractNo(bean.getContractId());
                        dto.getAssetList().add(rukuAsset);
                    }

                    break;
                // 配件
                case "2":
                    final AssetType assetType = this.assetTypeRepository.findByCode(asset.getAssetClassID());
                    final RukuKJGoodsFileDTO goodsFile = new RukuKJGoodsFileDTO();
                    goodsFile.setName(asset.getAssetName());
                    goodsFile.setSpareTypeCode(assetType != null ? assetType.getCode() : asset.getAssetClassID());
                    goodsFile.setSpareTypeName(assetType != null ? assetType.getName() : "");
                    goodsFile.setSpecification(asset.getAssetModel());

                    dto.getGoodsFileList().add(goodsFile);
                    break;
                default:
                    break;
                }
            }
        }
        final UserBean user = this.authMicroService.loadUserByUsername(bean.getContractUser()).getData();

        return this.create(dto, user);
    }

    @Transactional
    @Override
    public RukuKJDTO create(final RukuKJDTO dto, final UserBean user) {

        final String taskId = dto.getTaskId();

        // 设置操作人
        dto.setCreateUser(user.getUsername());
        dto.setCreateUserName(user.getName());

        // 暂存工单
        final ProcessInstanceDTO instance =
                this.workOrderService.submit(dto.getTitle(), DCAMConsts.PROCESSS_RUKU_KJ_KEY,
                        dto.getWorkOrderNum(), user);
        // 设置工单号
        dto.setWorkOrderNum(instance.getWorkorderNum());
        // 设置当前任务ID
        dto.setTaskId(instance.getTaskId());

        this.processInstanceService.setGlobalVariable(instance.getTaskId(), "autogenerate",
                dto.getAutogenerate());

        //判断是否为暂存状态
        if (!dto.getTemporary()) {
            this.processInstanceService.complete(dto.getWorkOrderNum(), instance.getTaskId(), user);

            try {
                // 对接ITSM
                final List<WorkflowBean.AssetBean> assetList = Lists.newArrayList();
                for (final RukuKJAssetDTO assetDTO : dto.getAssetList()) {
                    final WorkflowBean.AssetBean assetBean = WorkflowBean.AssetBean.builder()
                            .assetClassID(assetDTO.getSmallTypeCode())
                            .assetModel(StringUtils.isEmpty(assetDTO.getSpecifications()) ? "未知"
                                    : assetDTO.getSpecifications())
                            .assetUnit(assetDTO.getMeasureUnit())
                            .assetPrice(assetDTO.getMoney())
                            .assetNumber("3".equals(assetDTO.getCategories()) ? assetDTO.getAmount() : 1)
                            .assetName(assetDTO.getName())
                            .assetType("1")
                            .assetSign(
                                    StringUtils.isNoneBlank(assetDTO.getBrand()) ? assetDTO.getBrand()
                                            : "未知")
                            .build();
                    assetList.add(assetBean);
                }

                for (final RukuKJGoodsFileDTO assetDTO : dto.getGoodsFileList()) {
                    final WorkflowBean.AssetBean assetBean = WorkflowBean.AssetBean.builder()
                            .assetClassID(assetDTO.getSpareTypeCode())
                            .assetModel(StringUtils.isEmpty(assetDTO.getSpecification()) ? "未知"
                                    : assetDTO.getSpecification())
                            .assetUnit(assetDTO.getMeasureUnit())
                            .assetPrice(0)
                            .assetNumber(1)
                            .assetName(assetDTO.getName())
                            .assetType("2")
                            .assetSign("未知")
                            .build();
                    assetList.add(assetBean);
                }

                final WorkflowBean workflowBean = WorkflowBean.builder()
                        .workNum(dto.getWorkOrderNum())
                        .workName("设备入库")
                        .workType("10")
                        .workContent("设备入库申请")
                        .applyUser(user.getUsername())
                        .assetList(assetList)
                        .build();

                this.itsmService.pushItsm(workflowBean);
            } catch (final Exception e) {
                RukuKJServiceImpl.log.error("设备入库流程推送ITSM时发生错误", e);
            }
        }

        // 查询当前workNum和TaskId下是否存在记录
        final RukuKJ oldModel = this.rukuKJRepository.findByWorkOrderNumAndTaskId(
                dto.getWorkOrderNum(), taskId);

        // 如果不存在新增
        if (oldModel == null) {
            dto.setId(null);
        }

        final RukuKJ model = this.rukuKJConverter.toModel(dto);
        this.rukuKJRepository.save(model);

        return this.rukuKJConverter.toDTO(model);
    }

    @Override
    public RukuKJDTO detail(final String workOrderNum, final String taskId, final UserBean user) {
        RukuKJ model = null;
        try {
            if (StringUtils.isNotBlank(workOrderNum) && !"NULL".equals(taskId)) {
                model = this.rukuKJRepository.findByWorkOrderNumAndTaskId(workOrderNum, taskId);
                if (model == null) {
                    // 获取前一节点的TaskID
                    final String fromProcessTaskId = this.processInstanceService.getLastTaskId(taskId, user);
                    if (fromProcessTaskId == null) {
                        return new RukuKJDTO();
                    } else {
                        model = this.rukuKJRepository.findByWorkOrderNumAndTaskId(workOrderNum, fromProcessTaskId);
                    }
                }
            } else if ("NULL".equals(taskId)) {
                model = this.rukuKJRepository.findTopByWorkOrderNumOrderByIdDesc(workOrderNum);
            }
        } catch (final EntityNotFoundException e) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND,
                    new Object[] {workOrderNum },
                    new Object[] {taskId });
        }
        return this.rukuKJConverter.toDTO(model);
    }

    @Override
    @Transactional
    public ITSMApproveDTO itsmCreate(final ITSMApproveDTO dto, final UserBean user) {
        final ITSMApprove model = this.approveConverter.toModel(dto);
        this.approveRepository.save(model);

        this.processInstanceService.setGlobalVariable(dto.getTaskId(), DCAMConsts.PROCESSS_APPROVE_RESULT,
                dto.getResult());
        // 完成当前节点
        this.processInstanceService.complete(dto.getWorkOrderNum(), dto.getTaskId(), user);

        return this.approveConverter.toDTO(model);
    }

    @Override
    public ITSMApproveDTO itsmDetails(final String workOrderNum, final String taskId, final UserBean user) {
        ITSMApprove model = null;
        try {
            if (StringUtils.isNotBlank(workOrderNum) && !"NULL".equals(taskId)) {
                model = this.approveRepository.findByWorkOrderNumAndTaskId(workOrderNum, taskId);
                if (model == null) {
                    // 获取前一节点的TaskID
                    final String lastTaskId = this.processInstanceService.getLastTaskId(taskId, user);
                    if (lastTaskId == null) {
                        return new ITSMApproveDTO();
                    } else {
                        model = this.approveRepository.findByWorkOrderNumAndTaskId(workOrderNum,
                                lastTaskId);
                    }
                }
            } else if ("NULL".equals(taskId)) {
                final List<ITSMApprove> arrivalMains =
                        this.approveRepository.findAllByWorkOrderNumOrderByCreateTimeDesc(workOrderNum);
                if ((arrivalMains != null) && (arrivalMains.size() > 0)) {
                    model = arrivalMains.get(0);
                }
            }
        } catch (final EntityNotFoundException e) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND,
                    new Object[] {workOrderNum },
                    new Object[] {taskId });
        }
        return this.approveConverter.toDTO(model);
    }

    @Transactional
    @Override
    public ITSMApproveDTO confirm(final ITSMApproveDTO dto, final UserBean user) {
        // 完成当前节点
        this.processInstanceService.complete(dto.getWorkOrderNum(), dto.getTaskId(), user);
        this.generateAssets(dto.getWorkOrderNum());
        this.saveTemporary(dto.getWorkOrderNum());
        return dto;
    }

    private List<AssetDTO> generateAssets(final String workOrderNum) {
        final List<AssetDTO> list = new ArrayList<>();
        final List<AssetLifeCycleDTO> lifeList = new ArrayList<>();
        final List<WarehouseRecordDTO> records = new ArrayList<>();

        final RukuKJ main = this.rukuKJRepository.findTopByWorkOrderNumOrderByCreateTimeDesc(workOrderNum);

        switch (main.getCategories()) {
        // 消耗品
        case "3":
            main.getAssetList().forEach(l -> {

                final Asset xhAsset = this.assetRepository
                        .findTopBySmallTypeCodeAndBelongsAndManagementOrgCodeOrderByCreateTimeDesc(
                                l.getSmallTypeCode(), "kj", null);

                final AssetDTO asset = new AssetDTO();

                // 存在的情况添加数量
                if (null != xhAsset) {
                    xhAsset.setAmount(xhAsset.getAmount() + l.getAmount());
                    this.assetRepository.save(xhAsset);
                    // 生命周期
                    lifeList.add(AssetLifeCycleDTO.builder().userName(main.getCreateUserName()).code(xhAsset.getCode())
                            .lifeCycle(DCAMConsts.ASSET_LIFE_TYPE_DAOHU)
                            .content(xhAsset.getSmallTypeName() + "物资入库,入库数量为" + l.getAmount()).workNum(workOrderNum)
                            .build());
                } else {

                    asset.setName(l.getName());
                    asset.setPurchaseDate(l.getPurchaseDate());
                    asset.setSpecifications(l.getSpecifications());
                    asset.setMoney(l.getMoney());
                    // 存储合同信息 ge.x 2022-04-08
                    asset.setContractName(l.getContractName());
                    asset.setContractNo(l.getContractNo());
                    asset.setSmallTypeCode(l.getSmallTypeCode());
                    asset.setSmallTypeName(l.getSmallTypeName());
                    asset.setAmount(l.getAmount());
                    asset.setBrand(l.getBrand());
                    asset.setCategories(l.getCategories());
                    asset.setLocation(main.getLocation());
                    asset.setLocationName(main.getLocationName());
                    asset.setBelongs(AHConstants.BELONG_KJ_CODE);
                    asset.setStatus(DCAMConsts.ASSET_STATUS_UNUSED);

                    asset.setMiddleTypeCode(l.getMiddleTypeCode());
                    asset.setMiddleTypeName(l.getMiddleTypeName());
                    asset.setBigTypeCode(l.getBigTypeCode());
                    asset.setBigTypeName(l.getBigTypeName());
                    asset.setNote(l.getNote());

                    final AssetDTO dto = this.assetService.create(asset, null, null);
                    // 生命周期
                    lifeList.add(AssetLifeCycleDTO.builder().userName(main.getCreateUserName()).code(dto.getCode())
                            .lifeCycle(DCAMConsts.ASSET_LIFE_TYPE_DAOHU)
                            .content(dto.getName() + "物资入库,入库数量为" + l.getAmount()).workNum(workOrderNum)
                            .build());
                }

                // 库房记录
                records.add(WarehouseRecordDTO.builder()
                        .name(l.getSmallTypeName())
                        .specifications(l.getSpecifications())
                        .brand(l.getBrand())
                        .smallTypeName(l.getSmallTypeName())
                        .smallTypeCode(l.getSmallTypeCode())
                        .contractNo(main.getContractCode())
                        .contractName(main.getContractName()).amount(l.getAmount()).location(main.getLocation())
                        .locationName(main.getLocationName()).type("1").build());

            });

            break;

        default:
            main.getAssetList().forEach(l -> {
                AssetDTO asset = new AssetDTO();
                asset.setName(l.getName());
                asset.setPurchaseDate(l.getPurchaseDate());
                asset.setSpecifications(l.getSpecifications());
                asset.setMoney(l.getMoney());
                // 存储合同信息 ge.x 2022-04-08
                asset.setContractName(l.getContractName());
                asset.setContractNo(l.getContractNo());
                asset.setSmallTypeCode(l.getSmallTypeCode());
                asset.setSmallTypeName(l.getSmallTypeName());
                asset.setBrand(l.getBrand());
                asset.setLocation(main.getLocation());
                asset.setLocationName(main.getLocationName());
                asset.setMaintenanceStartTime(l.getMaintenanceStartTime());
                asset.setMaintenanceEndTime(l.getMaintenanceEndTime());
                asset.setMeasureUnit(l.getMeasureUnit());
                asset.setUsePeriod(l.getUsePeriod());
                asset.setAmount(1);
                asset.setSerialnumber(l.getSerialnumber());
                asset.setCategories(main.getCategories());
                asset.setBelongs(AHConstants.BELONG_KJ_CODE);
                asset.setStatus(DCAMConsts.ASSET_STATUS_UNUSED);
                asset.setSupplierName(l.getSupplierName());
                asset.setMiddleTypeCode(l.getMiddleTypeCode());
                asset.setMiddleTypeName(l.getMiddleTypeName());
                asset.setBigTypeCode(l.getBigTypeCode());
                asset.setBigTypeName(l.getBigTypeName());
                asset.setNote(l.getNote());
                asset.setPurpose(l.getPurpose());
                asset = this.assetService.create(asset, null, null);

                // 生命周期
                lifeList.add(AssetLifeCycleDTO.builder().code(asset.getCode())
                        .lifeCycle(DCAMConsts.ASSET_LIFE_TYPE_DAOHU)
                        .content(asset.getName() + "已入库").workNum(workOrderNum).build());

            });

            main.getGoodsFileList().forEach(s -> {
                final GoodsFileDTO goodsFileDto = new GoodsFileDTO();
                goodsFileDto.setName(s.getName());
                goodsFileDto.setSpareTypeCode(s.getSpareTypeCode());
                goodsFileDto.setSpecification(s.getSpecification());
                goodsFileDto.setDescription(s.getDescription());
                this.goodsFileService.create(goodsFileDto);
            });
            break;

        }

        if (records.size() > 0) {
            this.warehouseRecordService.batchCreate(records);
        }

        if (lifeList.size() > 0) {
            this.assetLifeCycleService.batchCreate(lifeList);
        }

        return list;
    }

    private List<WorkOrderDeposit> saveTemporary(final String workNum) {
        final List<WorkOrderDeposit> depositList = new ArrayList<>();
        final List<RukuKJ> rukuKJs =
                this.rukuKJRepository.findAllByWorkOrderNumOrderByCreateTimeDesc(workNum);
        //获取已有库存的宝贝
        final Searchable searchable = new Searchable();
        searchable.put("categories", "3");
        final List<Asset> assetList = this.assetRepository.search(searchable);
        //判断申请入库的消耗品是否为空
        if (!CollectionUtils.isEmpty(rukuKJs)) {
            //获取申请入库的宝贝信息
            final RukuKJ rukuKJ = rukuKJs.get(0);
            final List<RukuKJAsset> rukuList = rukuKJ.getAssetList();
            rukuList.stream().forEach(ruku -> {
                if ("3".equals(ruku.getCategories())) {
                    int i = 0;
                    for (final Asset asset : assetList) {
                        if (asset.getSmallTypeName().equals(ruku.getSmallTypeName())) {
                            i = 1;
                            final WorkOrderDeposit model = new WorkOrderDeposit();
                            model.setWorkOrderNum(workNum);
                            model.setSmallTypeCode(asset.getSmallTypeCode());
                            model.setSmallTypeName(asset.getSmallTypeName());
                            model.setQuantity(asset.getAmount());
                            depositList.add(model);
                        }
                    }
                    if (i == 0) {
                        final WorkOrderDeposit model = new WorkOrderDeposit();
                        model.setWorkOrderNum(workNum);
                        model.setSmallTypeCode(ruku.getSmallTypeCode());
                        model.setSmallTypeName(ruku.getSmallTypeName());
                        model.setQuantity(ruku.getAmount());
                        depositList.add(model);
                    }
                }
            });
            this.workOrderDepositRepository.saveAll(depositList);
        }
        return depositList;
    }

}
